import json

import urllib3
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer

from dashboard.k8s import ContainerLog, K8SLogStreamThread, ContainerSSH, K8SSSHStreamThread

urllib3.disable_warnings()


class LogConsumer(WebsocketConsumer):
    # websocket建立连接时执行方法
    def connect(self):
        # 从url里获取相关参数
        self.namespace = self.scope['url_route']['kwargs']['namespace']
        self.pod_name = self.scope['url_route']['kwargs']['pod_name']
        self.container_name = self.scope['url_route']['kwargs']['container_name']
        self.k8s_channel_name = 'chat_%s_%s_%s' % (self.namespace, self.pod_name, self.container_name)
        self.log_api = ContainerLog(self.scope)
        self.stream = None

        # 将当前频道加入频道组
        async_to_sync(self.channel_layer.group_add)(
            self.k8s_channel_name,
            self.channel_name
        )

        # 接受所有websocket请求
        self.accept()
        self._int()

    # websocket断开时执行方法
    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            self.k8s_channel_name,
            self.channel_name
        )

    # # 从websocket接收到消息时执行函数，日志只发送不接收消息
    # def receive(self, text_data):
    #     # text_data_json = json.loads(text_data)
    #     # message = text_data_json['message']
    #
    #     # 发送消息到频道组，频道组调用chat_message方法
    #     async_to_sync(self.channel_layer.group_send)(
    #         self.k8s_channel_name,
    #         {
    #             'type': 'chat_message',
    #             'message': text_data
    #         }
    #     )

    # 从频道组接收到消息后执行方法
    def chat_message(self, event):
        print('chat_message: %s' % event)
        message = event['message']
        # datetime_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        # 通过websocket发送消息到客户端
        self.send(text_data=json.dumps({
            'message': f'{message}'
        }))

    def _int(self):
        try:
            self.stream = self.log_api.get_container_log(namespace=self.namespace, pod_name=self.pod_name,
                                                         container=self.container_name)
        except Exception as e:
            self.close()
            self.log_api.error_check(e)
            return
        K8SLogStreamThread(self, self.stream).start()


class SSHConsumer(WebsocketConsumer):
    # websocket建立连接时执行方法
    def connect(self):
        self.namespace = self.scope['url_route']['kwargs']['namespace']
        self.pod_name = self.scope['url_route']['kwargs']['pod_name']
        self.container_name = self.scope['url_route']['kwargs']['container_name']
        self.rows = self.scope['url_route']['kwargs']['rows']
        self.cols = self.scope['url_route']['kwargs']['cols']
        self.k8s_channel_name = 'chat_%s_%s_%s' % (self.namespace, self.pod_name, self.container_name)
        try:
            self.api = ContainerSSH(self.scope)
        except:
            return self.api
        self.stream = None

        # 将当前频道加入频道组
        async_to_sync(self.channel_layer.group_add)(
            self.k8s_channel_name,
            self.channel_name
        )

        # 接受所有websocket请求
        self.accept()
        self._int()

    # websocket断开时执行方法
    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            self.k8s_channel_name,
            self.channel_name
        )

    # 从频道组接收到消息后执行方法
    def chat_message(self, event):
        # print('chat_message: %s' % event)
        message = event['message']

        # 通过websocket发送消息到客户端
        self.send(text_data=json.dumps({
            'message': f'{message}'
        }))

    def _int(self):
        try:
            self.stream = self.api.ssh_pod(namespace=self.namespace, pod_name=self.pod_name,
                                           container=self.container_name, rows=self.rows, cols=self.cols)
        except Exception as e:
            self.close()
            self.api.error_check(e)
            return
        K8SSSHStreamThread(self, self.stream).start()

    # 从websocket接收到消息时执行函数
    def receive(self, text_data=None, bytes_data=None):
        # 调用ssh_pod 将前端传回的命令发送给pod
        self.stream.write_stdin(text_data)
